package thesis;

import java.util.HashMap;
import java.util.Hashtable;
import java.util.Random;


import org.apache.commons.math3.distribution.NormalDistribution;

import com.mongodb.DBObject;

import experiment.Dimension;

public class LocationManager {
	private static final int APPROXIMATENUMBEROFLOCATIONS = 22;

	private Dimension locationDictionary = new Dimension();

	private LocationBounds locationBounds;

	private int numberOfRows;
	private int numberOfCols;

	private int numberOfCategories;

	public LocationManager(LocationBounds areaOfInterest) {
		locationBounds = areaOfInterest;

		double bl_lat;
		double bl_lon;
		double ur_lat;
		double ur_lon;

		if (locationBounds == null) {
			// Convention: United States as area of the event;
			bl_lat = 24;
			bl_lon = -126;
			ur_lat = 52;
			ur_lon = -62;
		} else {
			bl_lat = locationBounds.getBottomleft_lat();
			bl_lon = locationBounds.getBottomleft_lon();
			ur_lat = locationBounds.getUpperright_lat();
			ur_lon = locationBounds.getUpperright_lon();
		}

		double lat_range = Math.abs(bl_lat - ur_lat);
		double lon_range = Math.abs(bl_lon - ur_lon);

		double approximateNumberOfCols = Math.sqrt(APPROXIMATENUMBEROFLOCATIONS
				* lon_range / lat_range);
		double approximateNumberOfRows = APPROXIMATENUMBEROFLOCATIONS
				/ approximateNumberOfCols;

		numberOfCols = (int) Math.round(approximateNumberOfCols);
		numberOfRows = (int) Math.round(approximateNumberOfRows);

		numberOfCategories = numberOfCols * numberOfRows;
	}

	public boolean isInsideAreaOfEvent(DBObject tweet) {
		// Convention: if the tweet has not geo coordinates, it returns true
		InputTweetInfoExtractor infoExtr = new InputTweetInfoExtractor(tweet);

		if (!infoExtr.hasCoordinates()) {
			return true;
		}

		double tweetLatitude = infoExtr.getLatitude();
		double tweetLongitude = infoExtr.getLongitude();

		double bl_lat;
		double bl_lon;
		double ur_lat;
		double ur_lon;

		if (locationBounds == null) {
			// Convention: United States as area of the event;
			bl_lat = 24;
			bl_lon = -126;
			ur_lat = 52;
			ur_lon = -62;
		} else {
			bl_lat = locationBounds.getBottomleft_lat();
			bl_lon = locationBounds.getBottomleft_lon();
			ur_lat = locationBounds.getUpperright_lat();
			ur_lon = locationBounds.getUpperright_lon();
		}

		if (bl_lat <= ur_lat) {
			if (!(tweetLatitude >= bl_lat && tweetLatitude <= ur_lat))
				return false;
		} else {
			if (!(tweetLatitude <= bl_lat && tweetLatitude >= ur_lat))
				return false;
		}

		if (bl_lon <= ur_lon) {
			if (!(tweetLongitude >= bl_lon && tweetLongitude <= ur_lon))
				return false;
		} else {
			if (!(tweetLongitude <= bl_lon && tweetLongitude >= ur_lon))
				return false;
		}

		return true;
	}

	public String categorize(DBObject tweet) {
		InputTweetInfoExtractor infoExtr = new InputTweetInfoExtractor(tweet);
		long tweetId = infoExtr.getId();
		String locationCategory = null;

		if (!infoExtr.hasCoordinates()) {
//			int rd = new Random().nextInt(numberOfRows);
//			int cd = new Random().nextInt(numberOfCols);
//			for (int i = 0; i < numberOfRows; i++) {
//				for (int j = 0; j < numberOfCols; j++) {
//					HashMap<Long, Double> tweetsRelatedToLoc = locationDictionary
//							.get("r" + i + "c" + j);
//					if (tweetsRelatedToLoc == null) {
//						tweetsRelatedToLoc = new HashMap<Long, Double>();
//						locationDictionary.put("r" + i + "c" + j,
//								tweetsRelatedToLoc);
//					}
//					double rp = new NormalDistribution(rd, 2).density(i);
//					double cp = new NormalDistribution(cd, 2).density(i);
//					tweetsRelatedToLoc.put(tweetId, rp * cp);
//				}
//			}
		} else {

			double tweetLatitude = infoExtr.getLatitude();
			double tweetLongitude = infoExtr.getLongitude();

			double bl_lat;
			double bl_lon;
			double ur_lat;
			double ur_lon;
			if (locationBounds == null) {
				// Convention: United States as area of the event;
				bl_lat = 24;
				bl_lon = -126;
				ur_lat = 52;
				ur_lon = -62;
			} else {
				bl_lat = locationBounds.getBottomleft_lat();
				bl_lon = locationBounds.getBottomleft_lon();
				ur_lat = locationBounds.getUpperright_lat();
				ur_lon = locationBounds.getUpperright_lon();
			}

			int row;
			int col;

			double lat_range = Math.abs(bl_lat - ur_lat);
			double lon_range = Math.abs(bl_lon - ur_lon);

			double lat_cat_range = lat_range / numberOfRows;
			double lon_cat_range = lon_range / numberOfCols;

			double tempLat = Math.abs(tweetLatitude - bl_lat);
			row = (int) Math.round(Math.floor(tempLat / lat_cat_range));

			double tempLon = Math.abs(tweetLongitude - bl_lon);
			col = (int) Math.round(Math.floor(tempLon / lon_cat_range));

			locationCategory = "r" + row + "c" + col;

			HashMap<Long, Double> tweetsRelatedToLoc = locationDictionary
					.value2obj.get(locationCategory);
			if (tweetsRelatedToLoc == null) {
				tweetsRelatedToLoc = new HashMap<Long, Double>();
				locationDictionary.value2obj.put(locationCategory, tweetsRelatedToLoc);
			}
			tweetsRelatedToLoc.put(tweetId, 1.0);
		}

		return locationCategory;
	}

	public Dimension getLocationDictionary() {
		return locationDictionary;
	}
}
